package czy.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;

@RestController
@RequestMapping("/queue")
public class SendController {

    private static final Logger logger = LoggerFactory.getLogger(SendController.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送消息到指定的exchange,指定的队列,指定的routingKey
     */
    @PostMapping("/send/{exchange}/{queue}/{key}")
    public String sendToQueue(
            @PathVariable String exchange,
            @PathVariable String queue,
            @PathVariable String key,
            @RequestBody String body){

        /* 单独创建的队列,绑定到默认交换器,即空字符串,并以queue名称为键 */
        if(exchange.equals("null")){
            exchange="";
        }
        if(key.equals("null")){
            key = queue;
        }

        MessageProperties properties = new MessageProperties();

        /**
         *  appid是AMQP协议里定义的消息头之一,并未在协议中使用,可以在应用程序内赋予意义
         *  按照字面意思应该用于标识消息发送者所在的应用程序
         */
        properties.setAppId("appid");

        /* 也是可以自由使用的字段,按照字面意思,应该用于标识唯一一条消息 */
        properties.setMessageId("messageid");

        /* 关联id,类似于messageId */
        properties.setCorrelationId("correlationId");

        /* clusterid,没有明确意义,最好不要使用 */
        //properties.setClusterId("clusterid");

        /**
         * 消息收货模式,主要有持久化与非持久化两种
         * 持久化的意思是在写入队列之前需要写入磁盘,与druable队列 交换机一起使用可以防止消息因服务重启丢失
         * 性能影响非常大
         */
        properties.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);

        /* 设置交货标签,当收货模式为手动时,消费者可以通过收获标签确认收货 */
        properties.setDeliveryTag(new Date().getTime());

        /* 消息类型,AMQP协议中规定表示消息体mime类型,接收到的消息体为字节数组,应用程序可以根据mime类型对字节数组进行解析 */
        properties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);

        /* 发送到的消息队列 */
        properties.setConsumerQueue(queue);

        /* 使用消息体,消息头构造消息 */
        Message message = new Message(body.getBytes(),properties);

        /* 关联数据,在服务端发送应答时会携带它,ack,错误原因 */
        CorrelationData correlationData = new CorrelationData(new Date().toString());

        /* 发送消息到指定的exchange routingkey,这个方法无法确认消息投递成功 */
        this.rabbitTemplate.send(exchange,key,message,correlationData);


        /* 这个方法不是用于接收服务器应答的 */
        //Message ack = this.rabbitTemplate.sendAndReceive(exchange,key,message);


        return "消息发送成功";
    }


}
